package com.vinny.springbootflowable2.controller;

import com.vinny.springbootflowable2.exception.UnauthorizedException;
import com.vinny.springbootflowable2.model.ApiResponse;
import com.vinny.springbootflowable2.model.SysUser;
import com.vinny.springbootflowable2.model.dto.ExpenseDTO;
import com.vinny.springbootflowable2.model.vo.ProcessDiagramVO;
import com.vinny.springbootflowable2.service.ExpenseService;
import com.vinny.springbootflowable2.util.UserSessionUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.flowable.task.api.Task;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;

@Tag(name = "报销流程", description = "报销申请及审批相关操作，包括提交申请、任务处理、流程图查看等功能")
@RestController
@RequestMapping("/expense")
@RequiredArgsConstructor
public class ExpenseProcessController {

    private final ExpenseService expenseService;

    @Operation(
        summary = "提交报销申请",
        description = "创建新的报销申请流程，返回流程实例ID"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "申请提交成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "请求参数验证失败"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @PostMapping("/add")
    public ApiResponse<String> addExpense(
        @Parameter(description = "报销申请信息", required = true) 
        @Valid @RequestBody ExpenseDTO expenseDTO
    ) {
        SysUser currentUser = getCurrentUser();
        String processId = expenseService.submitExpense(currentUser.getLoginName(), expenseDTO);
        return ApiResponse.success("提交成功", processId);
    }

    @Operation(
        summary = "获取任务列表",
        description = "获取当前用户的待办任务列表"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "成功获取任务列表"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @GetMapping("/list")
    public ApiResponse<List<Task>> list() {
        SysUser currentUser = getCurrentUser();
        List<Task> tasks = expenseService.getUserTasks(currentUser.getLoginName());
        return ApiResponse.success(tasks);
    }

    @Operation(
        summary = "审批通过",
        description = "审批通过指定的报销申请任务"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "审批通过成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "任务不存在或无权操作"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @PostMapping("/apply")
    public ApiResponse<Void> apply(
        @Parameter(description = "要审批的任务ID", required = true) 
        @RequestParam String taskId
    ) {
        SysUser currentUser = getCurrentUser();
        expenseService.approveTask(currentUser.getLoginName(), taskId);
        return ApiResponse.success("审批通过", null);
    }

    @Operation(
        summary = "驳回申请",
        description = "驳回指定的报销申请任务"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "驳回成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "任务不存在或无权操作"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @PostMapping("/reject")
    public ApiResponse<Void> reject(
        @Parameter(description = "要驳回的任务ID", required = true) 
        @RequestParam String taskId
    ) {
        SysUser currentUser = getCurrentUser();
        expenseService.rejectTask(currentUser.getLoginName(), taskId);
        return ApiResponse.success("已驳回", null);
    }

    @Operation(
        summary = "获取流程图(原始)",
        description = "获取指定流程实例的流程图（PNG格式）"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(
            responseCode = "200", 
            description = "成功获取流程图",
            content = @Content(mediaType = MediaType.IMAGE_PNG_VALUE)
        ),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "流程实例不存在"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @GetMapping(value = "/processDiagram", produces = MediaType.IMAGE_PNG_VALUE)
    public void genProcessDiagram(
        HttpServletResponse response,
        @Parameter(description = "流程实例ID", required = true) 
        @RequestParam String processId
    ) throws IOException {
        getCurrentUser();
        byte[] bytes = expenseService.generateProcessDiagram(processId);
        response.getOutputStream().write(bytes);
    }

    @Operation(
        summary = "获取增强流程图信息",
        description = "获取带有当前节点、历史节点等详细信息的流程图数据"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "成功获取流程图信息"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "流程实例不存在"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @GetMapping("/processDiagramInfo")
    public ApiResponse<ProcessDiagramVO> getProcessDiagramInfo(
        @Parameter(description = "流程实例ID", required = true) 
        @RequestParam String processId
    ) {
        getCurrentUser();
        ProcessDiagramVO diagramInfo = expenseService.getProcessDiagramInfo(processId);
        return ApiResponse.success(diagramInfo);
    }

    @Operation(
        summary = "获取流程节点信息",
        description = "获取指定流程实例的所有节点信息列表"
    )
    @ApiResponses(value = {
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "成功获取节点信息"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "流程实例不存在"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户未登录")
    })
    @GetMapping("/processNodeInfo")
    public ApiResponse<List<String>> getProcessNodeInfo(
        @Parameter(description = "流程实例ID", required = true) 
        @RequestParam String processId
    ) {
        getCurrentUser();
        List<String> nodeInfo = expenseService.getProcessNodeInfo(processId);
        return ApiResponse.success(nodeInfo);
    }

    private SysUser getCurrentUser() {
        SysUser user = UserSessionUtil.getCurrentUser();
        if (user == null) {
            throw new UnauthorizedException("用户未登录");
        }
        return user;
    }
}